package org.brownflat.lighthouse.monitoring.monitor;

import org.apache.log4j.Logger;
import org.brownflat.lighthouse.monitoring.action.Action;
import org.brownflat.lighthouse.monitoring.ci.Build;
import org.brownflat.lighthouse.monitoring.ci.Feed;
import org.brownflat.lighthouse.monitoring.ci.Monitorable;
import org.brownflat.lighthouse.monitoring.device.Device;

import java.util.List;

public class AnyBrokenBuildTask implements LighthouseTask {

    private List<Monitorable> monitorables;
    private Monitorable monitorable;
    private Action whenBroken;
    private Action whenNotBroken;
    private Action whenResetNeeded;
    private boolean broken = false;
    private String name = null;
    private Device device;
    private boolean active;
    private static final Logger LOG = Logger.getLogger(AnyBrokenBuildTask.class);

    public AnyBrokenBuildTask(String activeServer, String name, List<Monitorable> monitorables, Device device, Action reset, Action broken, Action notBroken) {
        this.monitorables = monitorables;
        this.device = device;
        this.whenBroken = broken;
        this.whenNotBroken = notBroken;
        this.whenResetNeeded = reset;
        this.name = name;

        for(Monitorable thisMonitorable : monitorables) {
            if(thisMonitorable.getName().equals(activeServer)) {
                this.monitorable = thisMonitorable;
            }
        }

        if(monitorable == null) {
            throw new RuntimeException(String.format("Could not find appropriate build server type from [%s]", activeServer));
        }
    }

    @Override
    public void run() {
        LOG.debug("Checking for any broken build");
        monitorable.run();
        if (monitorable.isBroken()) {
            if (!broken) {
                execute(whenResetNeeded);
            }

            broken = true;
            execute(whenBroken);
            LOG.error("BROKEN BUILD DETECTED.");
            Feed feed = monitorable.getLatestFeed();
            List<Build> brokenBuilds = feed.getCurrentlyBrokenBuilds();
            for(Build brokenBuild : brokenBuilds) {
                LOG.warn(brokenBuild.toString());
            }
        } else {
            if (broken) {
                LOG.error("BROKEN BUILD FIXED.");
                execute(whenResetNeeded);
            }
            LOG.info("BUILDS OK.");
            broken = false;
            execute(whenNotBroken);
        }
    }

    @SuppressWarnings("unchecked")
    private void execute(Action action) {
        LOG.debug("Action executing: " + action.getActionDescription());
        device.execute(action);
    }

    public Monitorable getMonitorable() {
        return monitorable;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public  Device getDevice() {
        return device;
    }

    @Override
    public boolean isActive() {
        return active;
    }

    @Override
    public void setActive(boolean value) {
        this.active = value;
    }
}
